package com.editso.haier.configure;


import com.editso.haier.annon.Admin;
import com.editso.haier.filter.JwtFilter;
import com.editso.haier.intercept.Intercept;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.*;

import javax.servlet.Filter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class HaierBeans {

    @Bean
    private SecurityManager securityManager(@Autowired Realm realm){
        DefaultSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(realm);
        return manager;
    }

    @Bean
    private ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager manager){
        ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
        filter.setSecurityManager(manager);
        Map<String, Filter> filterMap = new HashMap<>();
        Map<String, String> filterChainMap = new HashMap<>();
        filter.setFilters(filterMap);
        filter.setFilterChainDefinitionMap(filterChainMap);
        filterMap.put("jwt", jwtFilter());
        return filter;
    }

    private Filter jwtFilter(){
        return new JwtFilter();
    }
    


    @Bean("LifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn("LifecycleBeanPostProcessor")
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setUsePrefix(true);
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    private AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager manager){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(manager);
        return advisor;
    }


    @Bean
    private WebMvcConfigurer webMvcConfigurer(@Autowired ApplicationContext context){
        return new WebMvcConfigurer() {
            @Override
            public void configurePathMatch(PathMatchConfigurer configurer) {
                configurer.addPathPrefix("/admin", aClass -> aClass.getAnnotation(Admin.class) != null);
                configurer.addPathPrefix("/openapi", aClass -> aClass.getAnnotation(Admin.class) == null);
            }

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        .allowCredentials(true)
                        .allowedHeaders("*")
                        .allowedOriginPatterns("*")
                        .maxAge(3600);

            }

            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                Collection<Intercept> intercepts = context.getBeansOfType(Intercept.class).values();
                InterceptorRegistration registration;
                for (Intercept intercept : intercepts) {
                    registration = registry.addInterceptor(intercept);
                    intercept.handlerIntercept(registration);
                }
            }
        };
    }
}
